<?php
/**
 * 授权公众号
 *
 * Author: Zeon
 * Date: 2017/11/23
 * Created by Panxsoft.
 */
namespace App\Models\OpenWechat;

use App\Models\Customer\Customer;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;

/**
 * Class Authorizer
 *
 * @property int canceled - 是否取消授权
 * @property int id
 * @property string|null merchant_id - DB无索引，可为 null
 * @property string merchant_key
 * @property int service_type_info
 * @property string authorizer_appid
 * @property string nick_name
 * @property string auth_code
 * @property WechatUser[]|Collection wechatUsers
 * @property Customer[]|Collection customers
 *
 * @package App\OpenWechat
 * @mixin Builder
 */
class Authorizer extends Model
{
    use Authorizable;

    // 开放平台全网发布测试 APPID
    const PUBLIC_DEBUT_TEST_APPID = 'wx570bc396a51b8ff8';

    const STATUS_CANCELED = 1;
    const STATUS_AUTH = 0;

    const SERVICE_TYPE_INFO_SUBSCRIBE = 0; // 订阅号
    const SERVICE_TYPE_INFO_OLD_SUB = 1;  // 老订阅号
    const SERVICE_TYPE_INFO_SERVICE = 2; // 服务号

    const ID_MAGIC_MIRROR      = 4;  // 魔妆镜公众号 ID
    const AUTHORIZER_APPID_MUW = 'wx1baa8b350b0f8190';

    protected $table = 'authorizers';

    protected static $unguarded = true;

    protected $casts = [
        'canceled'      => 'int',
        'func_info'     => 'json',
        'business_info' => 'json',
        'service_type_info' => 'int',
    ];

    /**
     * 取消授权
     * @param string $appid
     * @return bool
     */
    public static function cancelAuth(string $appid): bool
    {
        $author = self::findByAppId($appid);

        if (! $author) return false;

        return $author->cancel();
    }

    public static function findByAppId(string $appid = null):? self
    {
        return (new self)->where('authorizer_appid' , $appid)->first();
    }

    public function cancel(): bool
    {
        return $this->update([
            'canceled' => self::STATUS_CANCELED
        ]);
    }

    public function isCanceled(): bool
    {
        return $this->canceled === self::STATUS_CANCELED;
    }

    public function isAuthorized(): bool
    {
        return $this->canceled === self::STATUS_AUTH;
    }

    /**
     * @test
     *
     * @param string $auth_code
     *
     * @return Authorizer|null
     */
    public static function findByAuthCode(string $auth_code): ?self
    {
        return (new self)->where(compact('auth_code'))->first();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany|WechatUser
     */
    public function wechatUsers()
    {
        return $this->hasMany(WechatUser::class, 'authorizer_id', 'id');
    }

    /**
     * @test
     *
     * @param array $authorizer_info
     * @param array $authorization_info
     * @param string|null $auth_code
     *
     * @see Mock::openWxGetAuthorizerInfo()
     * @return bool
     */
    public function updateAuthorizerInfo(array $authorizer_info,
                                         array $authorization_info,
                                         string $auth_code = null): bool
    {
        $data = [
            'authorizer_refresh_token' => $authorization_info['authorizer_refresh_token'],
            'func_info'                => $authorization_info['func_info'],

            'nick_name'         => $authorizer_info['nick_name'],
            'nick_name_unicode' => json_encode($authorizer_info['nick_name']),
            'head_img'          => $authorizer_info['head_img'],
            'service_type_info' => $authorizer_info['service_type_info']['id'],
            'verify_type_info'  => $authorizer_info['verify_type_info']['id'],
            'user_name'         => $authorizer_info['user_name'],
            'alias'             => $authorizer_info['alias'],
            'qrcode_url'        => $authorizer_info['qrcode_url'],
            'business_info'     => $authorizer_info['business_info'],
            'idc'               => $authorizer_info['idc'],
            'principal_name'    => $authorizer_info['principal_name'],
            'signature'         => $authorizer_info['signature'],
            'canceled'          => Authorizer::STATUS_AUTH,
        ];

        if ($auth_code) $data['auth_code'] = $auth_code;

        return $this->update($data);
    }

    public function canOperate(): bool
    {
        return ! $this->canceled;
    }

    public function wechatUserCenterUrl(): string
    {
        return config('app.url') . '/wx-system/?appid=' . $this->authorizer_appid . '#/user';
    }

    public function customers()
    {
        return $this->hasMany(Customer::class,'authorizer_id','id');
    }

    /**
     * 是否服务号
     *
     * @return bool
     */
    public function isTypeService(): bool
    {
        return $this->service_type_info === self::SERVICE_TYPE_INFO_SERVICE;
    }

    /**
     * 默认的有商户微信公众号
     *
     * @return Authorizer
     */
    public static function defaultMerchant(): self
    {
        return (new self)->find(self::ID_MAGIC_MIRROR);
    }
    
    public static function isRequestAppidMuw(): bool
    {
        static $isMuw;
        if (! is_null($isMuw)) {
            return $isMuw;
        }
        
        return $isMuw = request()->get('appid') === self::AUTHORIZER_APPID_MUW;
    }
}
